<?php
/**
 * Created by PhpStorm.
 * User: tsingsun
 * Date: 2018/1/19
 * Time: 上午11:20
 */

namespace tsingsun\swoole\db\mysql;


use tsingsun\swoole\db\mysql\PDO;
use yii\helpers\ArrayHelper;

class PDOStatement extends \PDOStatement
{
    public function __construct($pdo)
    {
        $this->pdo = $pdo;
    }

    /**
     * @var \tsingsun\swoole\db\mysql\PDO
     */
    private $pdo;
    private $sql;
    private $params;
    private $data;
    private $_index = -1;

    public function setQueryString($queryString)
    {
        $this->sql = $queryString;
    }

    public function bindValue($parameter, $value, $data_type = PDO::PARAM_STR)
    {
        $this->params[$parameter] = $value;
    }

    public function execute($input_parameters = null)
    {
        try {
            $this->data = $this->pdo->getClient()->query($this->getRawSql());
        } finally {
            $this->pdo->releaseConnect();
        }
        return is_array($this->data);
    }

    public function rowCount()
    {
        return count($this->data);
    }

    public function closeCursor()
    {
        return true;
    }

    public function bindParam($parameter, &$variable, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null)
    {
        parent::bindParam($parameter, $variable, $data_type, $length, $driver_options); // TODO: Change the autogenerated stub
    }

    /**
     * Returns the raw SQL by inserting parameter values into the corresponding placeholders in [[sql]].
     * Note that the return value of this method should mainly be used for logging purpose.
     * It is likely that this method returns an invalid SQL due to improper replacement of parameter placeholders.
     * @return string the raw SQL with parameter values inserted into the corresponding placeholders in [[sql]].
     */
    public function getRawSql()
    {
        if (empty($this->params)) {
            return $this->sql;
        }
        $params = [];
        foreach ($this->params as $name => $value) {
            if (is_string($name) && strncmp(':', $name, 1)) {
                $name = ':' . $name;
            }
            if (is_string($value)) {
                $params[$name] = $this->pdo->quote($value);
            } elseif (is_bool($value)) {
                $params[$name] = ($value ? 'TRUE' : 'FALSE');
            } elseif ($value === null) {
                $params[$name] = 'NULL';
            } elseif (!is_object($value) && !is_resource($value)) {
                $params[$name] = $value;
            }
        }
        if (!isset($params[1])) {
            return strtr($this->sql, $params);
        }
        $sql = '';
        foreach (explode('?', $this->sql) as $i => $part) {
            $sql .= (isset($params[$i]) ? $params[$i] : '') . $part;
        }

        return $sql;
    }

    /**
     * 生效于queryOne
     * @param null $fetch_style
     * @param int $cursor_orientation
     * @param int $cursor_offset
     * @return bool|mixed
     */
    public function fetch($fetch_style = null, $cursor_orientation = \PDO::FETCH_ORI_NEXT, $cursor_offset = 0)
    {
        if (empty($this->data)) {
            return false;
        }
        return $this->data[++$this->_index] ?? false;
    }

    public function fetchAll($fetch_style = null, $fetch_argument = null, $ctor_args = array())
    {
        if (empty($this->data)) {
            return [];
        }
        if ($fetch_style == PDO::FETCH_COLUMN) {
            $key = key($this->data[0]);
            return ArrayHelper::getColumn($this->data, $key);
        }
        return $this->data;
    }

    /**
     *
     * @param int $column_number
     * @return bool|mixed
     */
    public function fetchColumn($column_number = 0)
    {
        if (empty($this->data)) {
            return null;
        }
        $data = $this->data[++$this->_index];
        return current(array_slice($data,$column_number,1));
    }


}